
// 基础用法，继承
class headPet { // 宠物总店提供了最基础的出售，回购宠物的服务
    sellPet(name) { // 出售宠物
        console.log('出售一只宠物', name)
    }
    desert(name) { // 遗弃宠物
        console.log('遗弃一只宠物', name)
    }
}

class subPet extends headPet { // 宠物分店，我们提供搭配服务，以便更好地卖宠物
    constructor() {
        super()
    }
    sell(name) { // 出售宠物
        this.sellPet(name)
    }
    sellPetFood(name) { // 购买宠物食物送宠物活动
        console.log('搭配了一大波食粮')
        this.sellPet(name)
    }
    sellPetCage(name) { // 购买宠物笼子送宠物活动
        console.log('搭配一个大笼子')
        this.sellPet(name)
    }
}

const subPet1 = new subPet()
subPet1.sell('tom')
subPet1.sellPetFood('tom')
subPet1.sellPetCage('tom')



// 请求代理，缓存
function ajax(params) { // 实际发送请求方法
    console.log(`发送请求${params}`)
    return params + Math.random()
}
const storage = new Map();
function cache(params) { // 缓存模式
    if (storage.has(params)) {
        return storage.get(params)
    }
    const value = ajax(params)
    storage.set(params, value)
    return value
}

function proxyAjax(params) { // 代理ajax请求
    return cache(params)
}

console.log(proxyAjax(1)) // 发送参数为1的请求
console.log(proxyAjax(1)) // 发送相同参数为1的请求，cache读取到缓存，所以不再调用ajax方法，直接返回结果
console.log(proxyAjax(2)) // 发送参数为2的请求，此时未读取到缓存，直接调用ajax方法，从后台请求




// 埋点/函数劫持
const oldFetch = window.fetch;
function newFetch(url, init) { // 重新fetch方法，代理fetch本身的功能，添加埋点功能
    const { method = 'GET', body } = init || {};
    const fetchObj = {
      url: url,
      method: method,
      body: body,
      start: performance.now(),
    }
    
    ajaxEventTrigger.call(fetchObj, AJAX_START); // 自定义埋点监听方法
    
    return oldFetch.apply(this, arguments).then(function (response) {
      fetchObj.end = performance.now();
      if (response.ok) {
        ajaxEventTrigger.call(fetchObj, AJAX_END)
      } else {
        ajaxEventTrigger.call(fetchObj, AJAX_ERROR)
      }
      return response
    }).catch(function (error) {
      fetchObj.end = performance.now();
      fetchObj.error = error
      ajaxEventTrigger.call(fetchObj, AJAX_ERROR);
      throw error
    })
  }
  window.fetch = newFetch;





  // 缓存时间
  class Storage {

    constructor(props) { // 根据类型跟缓存时间，初始化缓存方法
      const { type, time } = props
      this.type = type
      this.time = time
      this.storageType = {
        local: 'localStorage',
        session: 'sessionStorage'
      }
    }
  
    setItem(key, value) { // 代理原生缓存方法，添加缓存时间
      window[this.storageType[this.type]].setItem(key, JSON.stringify({
        value,
        time: new Date().getTime()
      }));
    }
  
    getItem(key) { // 代理原生获取缓存方法，根据缓存时间，判断数据是否过期
      try {
        const { time, value } = JSON.parse(window[this.storageType[this.type]].getItem(key));
        const now = new Date().getTime()
        if (now > time + this.time) {
          window[this.storageType[this.type]].removeItem(key);
          return null
        } else {
          return value
        }
      } catch (e) {
        return null
      }
    }
  }
  
  const local = new Storage({ type: 'local', time: 30000 }) // 初始化localStorage,添加5分钟缓存时效
  const session = new Storage({ type: 'session', time: 30000 }) // 初始化sessionStorage,添加5分钟缓存时效
  local.setItem(1, 2)
  local.getItem(1)
  session.setItem(3, 4)
  session.getItem(3)


  
// class Storage {
//     instance = null;  //  单例模式
//     static getInstance() {
//         if (!instance) {
//             instance = new Storage();
//         }
//         return instance;
//     }
//     setItem = (key, value) => localStorage.setItem(key, value);
//     getItem = key => localStorage.getItem(key)
// }